package app

import (
	"fmt"
	"gitee.com/CrazyMage/lite-note/config"
	"gitee.com/CrazyMage/lite-note/internal/controller/http"
	"gitee.com/CrazyMage/lite-note/internal/repo/persistent"
	"gitee.com/CrazyMage/lite-note/internal/service/note"
	"gitee.com/CrazyMage/lite-note/internal/service/user"
	"gitee.com/CrazyMage/lite-note/pkg/httpserver"
	"gitee.com/CrazyMage/lite-note/pkg/logger"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"os"
	"os/signal"
	"syscall"
)

// Run creates objects via constructors.
func Run(cfg *config.Config) {
	l := logger.New(cfg.Log.Level)

	// Repository
	db, err := gorm.Open(mysql.Open(cfg.Mysql.URL), &gorm.Config{})
	if err != nil {
		l.Fatal(fmt.Errorf("app - Run - postgres.New: %w", err))
	}
	sqlDB, _ := db.DB()

	// close connections
	defer sqlDB.Close()

	userUseCase := user.New(
		persistent.NewUserRepo(db),
	)
	noteUsecase := note.New(
		persistent.NewNoteRepo(db),
	)

	httpServer := httpserver.New(httpserver.Port(cfg.HTTP.Port))
	http.NewRouter(httpServer.App, cfg,
		userUseCase,
		noteUsecase,
		l)

	httpServer.Start()

	// Waiting signal
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)

	select {
	case s := <-interrupt:
		l.Info("app - Run - signal: %s", s.String())
	case err = <-httpServer.Notify():
		l.Error(fmt.Errorf("app - Run - httpServer.Notify: %w", err))
	}

	// Shutdown
	err = httpServer.Shutdown()
	if err != nil {
		l.Error(fmt.Errorf("app - Run - httpServer.Shutdown: %w", err))
	}

}
